package com.dyh.quickdemozwei;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

@Slf4j
public class TestMyTimeFiberR1 {


    final  int free = 0;
    final  int inqueue = 1;

    @Setter@Getter
    static class MyTimeFiber{
        String name;
        Runnable runnable;
        int status;

        public MyTimeFiber(String name, Runnable runnable) {
            this.name = name;
            this.runnable = runnable;
        }

        ManagerThread manager;


        public static final void sleep(long time){
            assert  Thread.currentThread() instanceof ManagerThread;
            ((ManagerThread)Thread.currentThread()).current.fsleep(time);
        }

        void run(){
//            try {
//                runnable.run();
//            }

        }

        void fsleep(long time){
            log.info("manage={}",manager);
            manager.queueIn(this,time);
        }
    }


    class ManagerThread extends Thread{

        MyTimeFiber current;

        public void queueIn(MyTimeFiber myTimeFiber, long time) {

            for (int i=0;i<queue.length;i++){
                QueueNode node = queue[i];
                if (node==null){
                    myTimeFiber.status=inqueue;
                    queue[i] = new QueueNode(myTimeFiber,time);
                    break;
                }
            }

        }

        class QueueNode{
            long delay;
            MyTimeFiber fiber;

            public QueueNode(MyTimeFiber myTimeFiber,long delay) {
                this.fiber = myTimeFiber;
                this.delay =delay;
            }


        }

        MyTimeFiber[] fibers;
        QueueNode[] queue;
        long lastTime;
        long frame = 50;//50ms

        public ManagerThread(MyTimeFiber... fibers) {

            for (MyTimeFiber fiber : fibers) {
                fiber.setManager(this);
            }
            this.fibers = fibers;

            queue = new QueueNode[fibers.length];


        }


        long getDeltaTime(){
            return System.currentTimeMillis()-lastTime;
        }

        @Override
        public void run() {
            lastTime = System.currentTimeMillis();//第一次执行
            for (;;){

                /*1 处理活跃的*/
                for (MyTimeFiber fiber:fibers){
                    if (fiber.status==0){
                        current = fiber;
                        fiber.getRunnable().run();
                    }


                }

                /*2 处理队列中的*/
                for (int i=0;i<queue.length;i++){
                    QueueNode node = queue[i];
                    if (node==null)
                        continue;
                    if ((node.delay-=getDeltaTime())>0)
                        continue;
                    current = node.fiber;
                    node.fiber.getRunnable().run();
                    queue[i]=null;
                    node.fiber.status=0;
//                    queue[i]=null;
                }


                try {
                    Thread.sleep(frame);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                lastTime = System.currentTimeMillis();
            }

        }
    }


    @Test
    public void test(){
        MyTimeFiber f1 = new MyTimeFiber("f1",()->log.info("f1!"));
        MyTimeFiber f1_2 = new MyTimeFiber("f1_2",()->log.info("f1-2!"));
        MyTimeFiber f2 = new MyTimeFiber("f2",()->log.info("f2!"));
        MyTimeFiber f4 = new MyTimeFiber("f4",()->log.info("f4!"));
        MyTimeFiber f1_t = new MyTimeFiber("f1",()->{
            for (;;){

                log.info("f1_t!");
                MyTimeFiber.sleep(1000L);
            }
        });
        ManagerThread managerThread = new ManagerThread(
//                f1,f2,
                f1_t
                //,f1_2
        );
        managerThread.start();

//        f1.fsleep(1000L);
        f2.fsleep(2000L);
        f4.fsleep(4000L);

        try {
            managerThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
